package com.jf.cloud.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.jf.cloud.api.user.dto.FinanceDetailDTO;
import com.jf.cloud.api.user.feign.UserBalanceLogClient;
import com.jf.cloud.api.user.feign.UserFeignClient;
import com.jf.cloud.api.user.feign.UserLevelLogClient;
import com.jf.cloud.api.user.vo.FinanceDetailExcelVO;
import com.jf.cloud.api.user.vo.FinanceDetailVO;
import com.jf.cloud.api.user.vo.UserApiVO;
import com.jf.cloud.common.constant.PayType;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.util.PriceUtil;
import com.jf.cloud.order.constant.FinanceBizType;
import com.jf.cloud.order.manager.MongoOrderManager;
import com.jf.cloud.order.manager.MongoOrderRefundManager;
import com.jf.cloud.order.service.OrderFinanceService;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 订单财务
 * @author zz
 */
@Service
public class OrderFinanceServiceImpl implements OrderFinanceService {

    @Autowired
    private MongoOrderRefundManager mongoOrderRefundManager;
    @Autowired
    private UserBalanceLogClient userBalanceLogClient;
    @Autowired
    private UserLevelLogClient userLevelLogClient;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private MongoOrderManager mongoOrderManager;

    @Override
    public PageVO<FinanceDetailVO> pageFinanceDetail(PageDTO pageDTO, FinanceDetailDTO financeDetailDTO) {
        financeDetailDTO.setPageSize(pageDTO.getPageSize());
        financeDetailDTO.setPageNum(pageDTO.getPageNum());
        PageVO<FinanceDetailVO> result = new PageVO<>();
        if (Objects.equals(financeDetailDTO.getFinanceBizType(), FinanceBizType.ORDER.value())) {
            result = mongoOrderManager.pageOrderFinanceDetail(pageDTO, financeDetailDTO);
        }
        else if (Objects.equals(financeDetailDTO.getFinanceBizType(), FinanceBizType.REFUND.value())) {
            result = mongoOrderRefundManager.pageRefundFinanceDetail(pageDTO, financeDetailDTO);
        }
        else if (Objects.equals(financeDetailDTO.getFinanceBizType(), FinanceBizType.RECHARGE.value())) {
            ServerResponseEntity<PageVO<FinanceDetailVO>> balanceResponse = userBalanceLogClient.pageFinanceDetail(financeDetailDTO);
            if (!balanceResponse.isSuccess()) {
                throw new LuckException(balanceResponse.getMsg());
            }
            result = balanceResponse.getData();
        }
        else if (Objects.equals(financeDetailDTO.getFinanceBizType(), FinanceBizType.LEVEL.value())) {
            ServerResponseEntity<PageVO<FinanceDetailVO>> levelResponse = userLevelLogClient.pageFinanceDetail(financeDetailDTO);
            if (!levelResponse.isSuccess()) {
                throw new LuckException(levelResponse.getMsg());
            }
            result = levelResponse.getData();
        }else if (Objects.equals(financeDetailDTO.getFinanceBizType(), FinanceBizType.QRCODE.value())) {
            ServerResponseEntity<PageVO<FinanceDetailVO>> balanceQrCodeResponse = userBalanceLogClient.pageFinanceDetail(financeDetailDTO);
            if (!balanceQrCodeResponse.isSuccess()) {
                throw new LuckException(balanceQrCodeResponse.getMsg());
            }
            result = balanceQrCodeResponse.getData();
        }
        if (CollUtil.isNotEmpty(result.getList())) {
            List<Long> userIds = result.getList().stream().map(FinanceDetailVO::getUserId).collect(Collectors.toList());
            ServerResponseEntity<List<UserApiVO>> userResponse = userFeignClient.getUserByUserIds(userIds);
            if (!userResponse.isSuccess()) {
                throw new LuckException(userResponse.getMsg());
            }
            Map<Long, String> userMap = userResponse.getData().stream().collect(Collectors.toMap(UserApiVO::getUserId, UserApiVO::getNickName));
            for (FinanceDetailVO financeDetailVO : result.getList()) {
                String userName = userMap.get(financeDetailVO.getUserId());
                financeDetailVO.setUserName(Objects.isNull(userName) ? "用户已注销": userName);
            }
        }
        return result;
    }

    @Override
    public List<FinanceDetailExcelVO> listExcelFinanceDetail(FinanceDetailDTO financeDetailDTO) {
        List<FinanceDetailVO> listFinanceDetail = mongoOrderManager.listOrderFinanceDetail(financeDetailDTO);
        List<FinanceDetailVO> listRefundFinanceDetail = mongoOrderRefundManager.listRefundFinanceDetail(financeDetailDTO);
        if (CollUtil.isNotEmpty(listRefundFinanceDetail)) {
            listFinanceDetail.addAll(listRefundFinanceDetail);
        }
        List<FinanceDetailExcelVO> financeDetailExcelList = mapperFacade.mapAsList(listFinanceDetail, FinanceDetailExcelVO.class);
        ServerResponseEntity<List<FinanceDetailExcelVO>> balanceResponse = userBalanceLogClient.listFinanceDetail(financeDetailDTO);
        if (!balanceResponse.isSuccess()) {
            throw new LuckException(balanceResponse.getMsg());
        }
        if (CollUtil.isNotEmpty(balanceResponse.getData())) {
            financeDetailExcelList.addAll(balanceResponse.getData());
        }
        ServerResponseEntity<List<FinanceDetailExcelVO>> levelResponse = userLevelLogClient.listFinanceDetail(financeDetailDTO);
        if (!levelResponse.isSuccess()) {
            throw new LuckException(levelResponse.getMsg());
        }
        if (CollUtil.isNotEmpty(levelResponse.getData())) {
            financeDetailExcelList.addAll(levelResponse.getData());
        }
        if (CollUtil.isNotEmpty(financeDetailExcelList)) {
            financeDetailExcelList = financeDetailExcelList.stream().sorted(Comparator.comparing(FinanceDetailExcelVO::getTransDate).reversed()).collect(Collectors.toList());;
            List<Long> userIds = financeDetailExcelList.stream().map(FinanceDetailExcelVO::getUserId).collect(Collectors.toList());
            ServerResponseEntity<List<UserApiVO>> userResponse = userFeignClient.getUserByUserIds(userIds);
            if (!userResponse.isSuccess()) {
                throw new LuckException(userResponse.getMsg());
            }
            Map<Long, String> userMap = userResponse.getData().stream().collect(Collectors.toMap(UserApiVO::getUserId, UserApiVO::getNickName));
            for (FinanceDetailExcelVO financeDetailVO : financeDetailExcelList) {
                financeDetailVO.setUserName(userMap.get(financeDetailVO.getUserId()));
                financeDetailVO.setBizTypeStr(FinanceBizType.instance(financeDetailVO.getBizType()).str());
                financeDetailVO.setPayTypeName(PayType.getPayTypeName(financeDetailVO.getPayType()));
                financeDetailVO.setAmount(PriceUtil.toDecimalPrice(financeDetailVO.getTransAmount()).toString());
            }
        }
        return financeDetailExcelList;
    }
}
